#include "utils_aes.h"

#include "../debug.h"

#include <stdlib.h>
#include <linux/stddef.h>


static int toInt(char c)
{
	if(c >= 'a')
		return c - 'a' + 35;
	else if(c >= 'A')
		return c - 'A' + 10;
	else if(c >= '0')
		return c - '0';
	return -1;
}

// prints string as hex
static void phex(uint8_t* str, int l)
{
//    unsigned char i;
//    for(i = 0; i < l; ++i)
//        printf("%.2x", str[i]);
//    printf("\n");
}

/**
 * 加密
 */
uint8 *
utils_aesEncrypt2(uint8* key, uint8* input, int inlen)
{
	uint8 *buf = malloc(inlen + 1);
	memset(buf, 0, inlen + 1);

	/**
	 * AES加密以16字节为一段. 不足16字节的用0填充
	 */
	if(((inlen >> 4) << 4) < inlen) {
		inlen = ( (inlen >> 4) + 1 ) << 4;
	}

	int i, l;
	uint8 tmp[16];

	for(i = 0; i < inlen; i += 16)
	{
		l = (inlen - i)>16? 16 : inlen - i;

		memset(tmp, 0, 16);
		memcpy(tmp, input + i, l);

		AES128_ECB_encrypt(tmp, key, buf + i);
	}

	size_t ol = 0;
	uint8* ret = base64_encode(buf, inlen, &ol);
	free(buf);

	return ret;
}

uint8 *
utils_aesEncrypt(uint8* key, uint8* oritxt, int inlen)
{
    int i, realen;
    uint8 *res;
    aes_context ctx = {0};

    aes_set_key(&ctx, key, 128);	//使用128位加密

    /**
     * AES加密以16字节为一段. 不足16字节的用0填充
     */
    if( ( (inlen >> 4) << 4 ) < inlen ) {
    	realen = ( (inlen >> 4) + 1 ) << 4;
    } else {
    	realen = inlen;
    }

    res = malloc(sizeof(uint8) * realen + 1);
	memset(res, 0, realen + 1);

    uint8 iptbuf[16];
    for(i = 0; i < realen; i += 16)
    {
    	int cryptLen = (inlen - i)>16? 16 : inlen - i;

    	memset(iptbuf, 0, 16);
    	memcpy(iptbuf, oritxt+i, cryptLen);
		aes_encrypt(&ctx, iptbuf, iptbuf); //长度对齐
//		log_info("%d %d nr=%d", iptbuf[14], iptbuf[15], ctx.nr);
		memcpy(res+i, iptbuf, 16);
    }

//    log_info("res=%s", res);

    size_t ol = 0;
    uint8* ret = base64_encode(res, realen, &ol);
    free(res);

    return ret;
}

/**
 * 解密
 */
uint8 *
utils_aesDecrypt(uint8* key, uint8* dectxt, int inlen)
{
    int i, l;
    uint8 *res;
    unsigned char buf[16];
    aes_context ctx = {0};

    aes_set_key(&ctx, key, 128);	//使用128位加密

    size_t ol = 0;
    uint8* dec = base64_decode(dectxt, inlen, &ol);

    res = malloc(sizeof(uint8) * ol + 1);
	memset(res, 0, ol + 1);

    for(i = 0; i < ol; i += 16)
    {
    	l = (ol - i)>16? 16 : ol - i;

    	memset(buf, 0, 16);
		aes_decrypt(&ctx, dec + i, buf);
		memcpy(res + i, buf, l);
    }

//    phex(res, ol);

    //兼容 php 清理 非法字符
	for(i=0; i<ol; i++)
	{
		if(res[i] < 32)
			res[i] = 0;
	}
    free(dec);

	return res;
}


uint8*
utils_aesDecrypt3(uint8* dectxt, int inlen)
{
	if(!dectxt || inlen < 0)
		return NULL;

	int ki = toInt(dectxt[0]);
	int kl = toInt(dectxt[1]);

	if(ki < 0 || kl < 0)
		return NULL;

	uint8* ks = malloc(kl + 1);
	memset(ks, 0, kl + 1);
	strncpy(ks, dectxt + 2 + ki, kl);
	uint8* key = base64_decode(ks, kl, NULL);
	free(ks);

	if(!key)
		return NULL;

	int sl = inlen - 2 - kl;
	uint8* s = malloc(sl + 1);
	memset(s, 0, sl + 1);

	strncpy(s, dectxt + 2, ki);
	strcpy(s + ki, dectxt + 2 + ki + kl);

	uint8* ret = utils_aesDecrypt(key, s, sl);

	free(key);

	return ret;
}
